package com.lp.biz.train.service.impl;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lp.biz.category.mapper.BizCategoryMapper;
import com.lp.biz.category.model.entity.BizCategory;
import com.lp.biz.content.mapper.BizCoreContentMapper;
import com.lp.biz.content.mapper.BizCoreContentMemberRelMapper;
import com.lp.biz.content.model.entity.BizCoreContent;
import com.lp.biz.content.model.entity.BizCoreContentMemberRel;
import com.lp.biz.identity.mapper.BizIdentityMapper;
import com.lp.biz.identity.mapper.BizIdentityMemberRelMapper;
import com.lp.biz.identity.model.entity.BizIdentity;
import com.lp.biz.member.mapper.MemberMapper;
import com.lp.biz.member.model.entity.Member;
import com.lp.biz.message.model.entity.BizMessageSystem;
import com.lp.biz.message.service.BizMessageSystemService;
import com.lp.biz.message.service.BizMessageUpdateService;
import com.lp.biz.train.mapper.*;
import com.lp.biz.train.model.dto.TrainAssignMemberDto;
import com.lp.biz.train.model.dto.TrainMembersDto;
import com.lp.biz.train.model.entity.*;
import com.lp.biz.train.model.query.TrainChapterQuery;
import com.lp.biz.train.model.query.TrainClassQuery;
import com.lp.biz.train.model.query.TrainHomeworkQuery;
import com.lp.biz.train.model.query.TrainMembersQuery;
import com.lp.biz.train.model.vo.*;
import com.lp.biz.train.service.BizTrainService;
import com.lp.common.component.AliService;
import com.lp.common.context.UserDetail;
import com.lp.common.entity.CommonAll;
import com.lp.common.entity.PageParams;
import com.lp.common.exception.BaseException;
import com.lp.common.exception.ErrorCodeEnum;
import com.lp.common.poster.PosterService;
import com.lp.common.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.lp.common.component.CommonThreadPool.EXECUTOR;
import static com.lp.common.constant.CategoryConstant.CODE_TRAINING;
import static com.lp.common.constant.CommonConstant.NEGATE;
import static com.lp.common.constant.CommonConstant.SURE;
import static com.lp.common.constant.IdentityConstant.*;
import static com.lp.common.constant.TrainConstant.*;
import static com.lp.common.utils.Tools.*;

/**
 * @program: backend
 * @description: BizCoreContent 服务实现类
 * @author Ke.Song
 * @since 2024-05-02 10:45:20
 */
@Slf4j
@Service
public class BizTrainServiceImpl implements BizTrainService {

    @Autowired
    private AliService aliService;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private BizTrainMapper trainMapper;

    @Autowired
    private PosterService posterService;

    @Autowired
    private BizTrainClassMapper classMapper;

    @Autowired
    private BizCategoryMapper categoryMapper;

    @Autowired
    private BizIdentityMapper identityMapper;

    @Autowired
    private BizTrainTypeMapper trainTypeMapper;

    @Autowired
    private BizTrainChapterMapper chapterMapper;

    @Autowired
    private BizTrainHomeworkMapper homeworkMapper;

    @Autowired
    private BizCoreContentMapper coreContentMapper;

    @Autowired
    private BizMessageUpdateService messageUpdateService;

    @Autowired
    private BizMessageSystemService messageSystemService;

    @Autowired
    private BizTrainClassChapterRelMapper chapterRelMapper;

    @Autowired
    private BizTrainTaskMemberRelMapper taskMemberRelMapper;

    @Autowired
    private BizTrainHomeworkClassMapper homeworkClassMapper;

    @Autowired
    private BizTrainClassMemberRelMapper classMemberRelMapper;

    @Autowired
    private BizIdentityMemberRelMapper identityMemberRelMapper;

    @Autowired
    private BizCoreContentMemberRelMapper contentMemberRelMapper;

    @Override
    public CommonResult getTrainList(PageParams params) {
        PageHelper.startPage(params.getPage(), params.getSize());
        return CommonResult.restPage(trainMapper.getTrainList());
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void createTrain(CreateTrain createTrain) {
        BizCategory category = categoryMapper.selectOne(new QueryWrapper<BizCategory>().lambda().eq(BizCategory::getCode, CODE_TRAINING));
        if (category == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        checkType(createTrain.getTypeCode());
        BizCoreContent exitsContent = coreContentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getTitle, createTrain.getTitle()).eq(BizCoreContent::getIsDeleted, NEGATE));
        BizCoreContent bizCoreContent;
        if (createTrain.getId() == null) {
            if (exitsContent != null) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            bizCoreContent = generateTrain(createTrain, category, new BizCoreContent());
            coreContentMapper.insert(bizCoreContent);
            messageUpdateService.addUpdateMessage(bizCoreContent);
        } else {
            bizCoreContent = coreContentMapper.selectById(createTrain.getId());
            if (bizCoreContent == null || bizCoreContent.getIsDeleted().equals(SURE)) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            if (exitsContent != null && !exitsContent.getId().equals(createTrain.getId())) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            generateTrain(createTrain, category, bizCoreContent);
            coreContentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                    .eq(BizCoreContent::getId, bizCoreContent.getId())
                    .set(BizCoreContent::getBizCategoryId, bizCoreContent.getBizCategoryId())
                    .set(BizCoreContent::getBizCategoryCode, bizCoreContent.getBizCategoryCode())
                    .set(BizCoreContent::getBizLabelId, bizCoreContent.getBizLabelId())
                    .set(BizCoreContent::getTypeCode, bizCoreContent.getTypeCode())
                    .set(BizCoreContent::getTitle, bizCoreContent.getTitle())
                    .set(BizCoreContent::getDescription, bizCoreContent.getDescription())
                    .set(BizCoreContent::getContent, bizCoreContent.getContent())
                    .set(BizCoreContent::getImageT, bizCoreContent.getImageT())
                    .set(BizCoreContent::getImageV, bizCoreContent.getImageV())
                    .set(BizCoreContent::getVideoUrl, bizCoreContent.getVideoUrl())
                    .set(BizCoreContent::getAudioUrl, bizCoreContent.getAudioUrl())
                    .set(BizCoreContent::getIsCharge, bizCoreContent.getIsCharge())
                    .set(BizCoreContent::getIsDisplay, bizCoreContent.getIsDisplay())
                    .set(BizCoreContent::getDisplayAt, bizCoreContent.getDisplayAt())
                    .set(BizCoreContent::getOriginalPrice, bizCoreContent.getOriginalPrice())
                    .set(BizCoreContent::getActualPrice, bizCoreContent.getActualPrice())
                    .set(BizCoreContent::getDuration, bizCoreContent.getDuration())
                    .set(BizCoreContent::getIsRecommend, bizCoreContent.getIsRecommend())
                    .set(BizCoreContent::getAuthor, bizCoreContent.getAuthor())
                    .set(BizCoreContent::getNum, bizCoreContent.getNum())
                    .set(BizCoreContent::getReason, bizCoreContent.getReason())
                    .set(BizCoreContent::getCreateAt, bizCoreContent.getCreateAt())
                    .set(BizCoreContent::getUpdateAt, bizCoreContent.getUpdateAt())
                    .set(BizCoreContent::getProfile, bizCoreContent.getProfile())
                    .set(BizCoreContent::getIsDeleted, bizCoreContent.getIsDeleted()));
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteTrain(Integer trainId) {
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_TRAINING)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        coreContentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, trainId)
                .eq(BizCoreContent::getIsDeleted, NEGATE)
                .set(BizCoreContent::getIsDeleted, SURE));
        chapterMapper.update(null, new UpdateWrapper<BizTrainChapter>().lambda()
                .eq(BizTrainChapter::getBizTrainId, trainId)
                .set(BizTrainChapter::getIsDeleted, SURE));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void trainDisplay(Integer trainId) {
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        content.setIsDisplay(content.getIsDisplay().equals(SURE) ? NEGATE : SURE);
        coreContentMapper.updateById(content);
        coreContentMapper.update(null, new UpdateWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, content.getId())
                .set(BizCoreContent::getIsDisplay, content.getIsDisplay())
                .set(BizCoreContent::getDisplayAt, content.getIsDisplay().equals(NEGATE) ? null : LocalDateTime.now()));
    }

    @Override
    public CommonResult getTrainDetail(Integer trainId) {
        BizCoreContent content = coreContentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, trainId).eq(BizCoreContent::getBizCategoryCode, CODE_TRAINING));
        if (content == null || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        TrainDetail detail = new TrainDetail();
        detail.setId(content.getId());
        detail.setTitle(content.getTitle());
        detail.setTypeCode(content.getTypeCode());
        detail.setDescription(content.getDescription());
        detail.setImageV(content.getImageV());
        detail.setImageT(content.getImageT());
        detail.setActualPrice(stripTrailingZeros(content.getActualPrice()));
        detail.setOriginalPrice(stripTrailingZeros(content.getOriginalPrice()));
        detail.setCreateAt(content.getCreateAt());
        detail.setProfile(content.getProfile());
        detail.setIsDisplay(content.getIsDisplay());
        Long count = classMapper.selectCount(new QueryWrapper<BizTrainClass>().lambda()
                .eq(BizTrainClass::getBizTrainId, trainId));
        detail.setPeriodsNum(count == null ? 0 : count.intValue());
        detail.setIsCharge(content.getIsCharge());

        return CommonResult.success(detail);
    }

    @Override
    public CommonResult getTrainClasses(TrainClassQuery params) {
        BizCoreContent content = coreContentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, params.getTrainId()).eq(BizCoreContent::getBizCategoryCode, CODE_TRAINING));
        if (content == null || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        PageHelper.startPage(params.getPage(), params.getSize());
        List<TrainClass> classes = classMapper.getTrainClasses(params);
        for (TrainClass aClass : classes) {
            if (aClass.getStartAt() != null && aClass.getEndAt() != null) {
                LocalDate now = LocalDate.now();
                if (aClass.getStartAt().isAfter(now)) {
                    aClass.setStatus(CLASS_NOT_START);
                } else if (aClass.getEndAt().isBefore(now)) {
                    aClass.setStatus(CLASS_ENDED);
                } else {
                    aClass.setStatus(CLASS_STARTED);
                }
            }
        }
        return CommonResult.restPage(classes);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateClass(Integer trainId, CreateClass createClass) {
        // 根据培训ID和业务类别代码查询核心内容
        BizCoreContent content = coreContentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, trainId).eq(BizCoreContent::getBizCategoryCode, CODE_TRAINING));
        if (content == null || content.getIsDeleted().equals(SURE) || content.getIsDisplay().equals(NEGATE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (content.getIsCharge().equals(SURE) && createClass.getMentorIds().isEmpty()
                && createClass.getAssistantIds().isEmpty() && createClass.getTrainerId() ==null
                && createClass.getClassTeacherId() == null) {
            throw new BaseException("管理不能为空");
        }
        // 检查班级管理权限
        checkClassManage(content.getTypeCode(), createClass.getAssistantIds(), createClass.getMentorIds(),
                createClass.getTrainerId(), createClass.getClassTeacherId());

        // 初始化业务培训班级对象
        BizTrainClass bizTrainClass = new BizTrainClass();
        // 检查要添加的班级名称是否已存在
        BizTrainClass existC = classMapper.selectOne(new QueryWrapper<BizTrainClass>().lambda()
                .eq(BizTrainClass::getBizTrainId, trainId).eq(BizTrainClass::getName, createClass.getName())
                .eq(BizTrainClass::getIsDeleted, NEGATE));
        if (createClass.getId() == null && existC == null) {
            // 如果班级ID为空且不存在同名班级，则插入新班级信息
            bizTrainClass.setName(createClass.getName());
            bizTrainClass.setBizTrainId(trainId);
            bizTrainClass.setCreateAt(LocalDateTime.now());
            bizTrainClass.setTypeCode(content.getTypeCode());
            classMapper.insert(bizTrainClass);
            for (BizTrainHomework homework : homeworkMapper.selectList(new QueryWrapper<BizTrainHomework>().lambda()
                    .eq(BizTrainHomework::getBizTrainId, trainId).eq(BizTrainHomework::getIsDeleted, NEGATE))) {
                homeworkClassMapper.initHomeworkClass(homework);
            }
//        } else if (createClass.getId() != null && existC != null && createClass.getId().equals(existC.getId()) && existC.getBizTrainId().equals(trainId)) {
        } else if (createClass.getId() != null && existC == null) {
            // 如果班级ID不为空，且对应的是要修改的班级，则更新班级信息
            classMapper.update(null, new UpdateWrapper<BizTrainClass>().lambda()
                    .eq(BizTrainClass::getId, createClass.getId())
                    .set(BizTrainClass::getName, createClass.getName()));
            bizTrainClass = classMapper.selectById(createClass.getId());
        } else {
            // 否则，抛出参数错误异常
            throw new BaseException("班级已存在");
        }

        // 查询并构建身份映射
        Map<String, BizIdentity> identityMaps = new HashMap<>(6);
        for (BizIdentity bizIdentity : identityMapper.selectList(new QueryWrapper<BizIdentity>().lambda()
                .eq(BizIdentity::getTypeCode, content.getTypeCode())
                .in(BizIdentity::getCategory, CATEGORY_ASSISTANT, CATEGORY_MENTOR, CATEGORY_TRAINER))) {
            identityMaps.put(bizIdentity.getCategory(), bizIdentity);
        }

        // 初始化班级成员关系列表
        List<BizTrainClassMemberRel> relList = new ArrayList<>();
        // 处理班主任身份和关系
        BizIdentity bizIdentity = identityMapper.selectOne(new QueryWrapper<BizIdentity>().lambda()
                .eq(BizIdentity::getCode, CLASS_TEACHER));
        if (bizIdentity != null) {
            identityMaps.put(CLASS_TEACHER, bizIdentity);
            generateBizTrainClassMemberRel(trainId, bizTrainClass.getId(), relList, bizIdentity, createClass.getClassTeacherId());
        }

        // 处理助教、导师和培训师身份和关系
        bizIdentity = identityMaps.get(CATEGORY_ASSISTANT);
        if (bizIdentity != null) {
            for (Integer memberId : createClass.getAssistantIds()) {
                generateBizTrainClassMemberRel(trainId, bizTrainClass.getId(), relList, bizIdentity, memberId);
            }
        }
        bizIdentity = identityMaps.get(CATEGORY_MENTOR);
        if (bizIdentity != null) {
            for (Integer memberId : createClass.getMentorIds()) {
                generateBizTrainClassMemberRel(trainId, bizTrainClass.getId(), relList, bizIdentity, memberId);
            }
        }
        bizIdentity = identityMaps.get(CATEGORY_TRAINER);
        if (bizIdentity != null) {
            Integer memberId = createClass.getTrainerId();
            generateBizTrainClassMemberRel(trainId, bizTrainClass.getId(), relList, bizIdentity, memberId);
        }

        // 批量插入班级成员关系
        classMemberRelMapper.update(null, new UpdateWrapper<BizTrainClassMemberRel>().lambda()
                .eq(BizTrainClassMemberRel::getBizTrainClassId, bizTrainClass.getId())
                .set(BizTrainClassMemberRel::getIsDeleted, SURE));
        if (!relList.isEmpty()) {
            classMemberRelMapper.insertBatch(relList);
        }
        classMemberRelMapper.delete(new QueryWrapper<BizTrainClassMemberRel>().lambda()
                .eq(BizTrainClassMemberRel::getBizTrainClassId, bizTrainClass.getId())
                .eq(BizTrainClassMemberRel::getIsDeleted, SURE));
        classMapper.updateClassChapter(trainId);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void displayClass(Integer trainId, Integer classId) {
        BizCoreContent content = coreContentMapper.selectOne(new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getId, trainId).eq(BizCoreContent::getBizCategoryCode, CODE_TRAINING));
        if (content == null || content.getIsDisplay().equals(NEGATE) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        BizTrainClass bizTrainClass = classMapper.selectById(classId);
        if (bizTrainClass == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        if (bizTrainClass.getIsDisplay() == null || bizTrainClass.getIsDisplay().equals(SURE)) {
            bizTrainClass.setIsDisplay(NEGATE);
        } else {
            bizTrainClass.setIsDisplay(SURE);
        }
        classMapper.updateById(bizTrainClass);
    }

    @Override
    public CommonResult getTrainClass(Integer classId, Integer trainId) {
        BizTrainClass bizTrainClass = classMapper.selectById(classId);
        if (bizTrainClass == null || !bizTrainClass.getBizTrainId().equals(trainId)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        TrainClassManageDetail detail = new TrainClassManageDetail();
        detail.setId(bizTrainClass.getId());
        detail.setName(bizTrainClass.getName());
        detail.setAssistants(classMemberRelMapper.getClassManage(classId, CATEGORY_ASSISTANT));
        detail.setMentors(classMemberRelMapper.getClassManage(classId, CATEGORY_MENTOR));
        for (CommonAll commonAll : classMemberRelMapper.getClassManage(classId, CATEGORY_TRAINER)) {
            detail.setTrainer(commonAll);
        }

        for (CommonAll commonAll : classMemberRelMapper.getClassManage(classId, CLASS_TEACHER)) {
            detail.setClassTeacher(commonAll);
        }
        return CommonResult.success(detail);
    }

    @Override
    public CommonResult getTrainChapterList(Integer trainId, TrainChapterQuery query) {
        LambdaQueryWrapper<BizTrainChapter> queryWrapper = new QueryWrapper<BizTrainChapter>().lambda()
                .eq(BizTrainChapter::getBizTrainId, trainId).eq(BizTrainChapter::getIsDeleted, NEGATE)
                        .orderByAsc(BizTrainChapter::getSort).orderByAsc(BizTrainChapter::getId);
        if (query.getName() != null && !query.getName().trim().isEmpty()) {
            queryWrapper.like(BizTrainChapter::getName, query.getName().trim());
        }
        PageHelper.startPage(query.getPage(), query.getSize());
        List<BizTrainChapter> bizTrainChapters = chapterMapper.selectList(queryWrapper);
        Page<TrainChapterList> trainChapterLists = copyPage(new Page<>(), bizTrainChapters);
        for (BizTrainChapter chapter : bizTrainChapters) {
            TrainChapterList detail = new TrainChapterList();
            detail.setId(chapter.getId());
            detail.setTitle(chapter.getName());
            detail.setBizTrainId(chapter.getBizTrainId());
            detail.setDuration(chapter.getDuration());
            detail.setIsDisplay(chapter.getIsDisplay());
            detail.setSort(chapter.getSort());
            detail.setArrange(chapter.getArrange());
            detail.setContent(chapter.getContent());
            trainChapterLists.add(detail);
        }
        return CommonResult.restPage(trainChapterLists);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateChapter(Integer trainId, TrainChapterCreate params) {
        // 根据课程ID查询课程内容，确认课程存在且属于训练营
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_TRAINING) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        } else if (params.getIsDisplay() != 1 && params.getIsDisplay() != 0) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        } else if (params.getArrange() != null && !params.getArrange().equals(1) && !params.getArrange().equals(2)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        BizTrainChapter existChapter = chapterMapper.selectOne(new QueryWrapper<BizTrainChapter>().lambda()
                .eq(BizTrainChapter::getName, params.getName())
                .eq(BizTrainChapter::getIsDeleted, NEGATE));
        // 判断是添加新章节还是更新现有章节
        if (params.getId() == null) {
            if (existChapter != null) {
                throw new BaseException("章节名称重复");
            }
            // 添加新章节
            BizTrainChapter chapter = new BizTrainChapter();
            chapter.setName(params.getName());
            chapter.setBizTrainId(trainId);
            chapter.setVideoUrl(params.getVideoUrl());
            chapter.setPlaybackNum(params.getPlaybackNum());
            chapter.setIsDisplay(params.getIsDisplay());
            chapter.setDuration(params.getDuration());
            chapter.setArrange(params.getArrange() == null ? 1: params.getArrange());
            chapter.setContent(params.getContent());
            chapterMapper.insert(chapter);
            classMapper.updateClassChapter(trainId);
        } else {
            // 更新现有章节
            BizTrainChapter chapter = chapterMapper.selectById(params.getId());
            if (chapter == null) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            } else if (existChapter != null && (!existChapter.getId().equals(chapter.getId()) || !existChapter.getBizTrainId().equals(trainId))) {
                throw new BaseException("章节重复");
            }
            // 更新章节信息
            chapter.setName(params.getName());
            chapter.setBizTrainId(trainId);
            chapter.setVideoUrl(params.getVideoUrl());
            chapter.setPlaybackNum(params.getPlaybackNum() == null ? 0 : params.getPlaybackNum());
            chapter.setDuration(params.getDuration());
            chapter.setArrange(params.getArrange() == null ? 1: params.getArrange());
            chapter.setContent(params.getContent() == null ? "" : params.getContent());
            processChapterDisplay(chapter, params.getIsDisplay());
            chapterMapper.updateById(chapter);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteChapter(Integer trainId, Integer chapterId) {
        BizTrainChapter chapter = checkChapter(chapterId, trainId);
        chapter.setIsDeleted(SURE);
        chapterMapper.updateById(chapter);
        chapterRelMapper.update(null, new UpdateWrapper<BizTrainClassChapterRel>().lambda()
                .eq(BizTrainClassChapterRel::getBizTrainChapterId, chapter.getId())
                .set(BizTrainClassChapterRel::getIsDeleted, SURE));
    }

    @Override
    public CommonResult getChapter(Integer chapterId, Integer trainId) {
        BizTrainChapter chapter = checkChapter(chapterId, trainId);
        TrainChapterCreate trainChapterCreate = new TrainChapterCreate();
        trainChapterCreate.setId(chapterId);
        trainChapterCreate.setName(chapter.getName());
        trainChapterCreate.setVideoUrl(chapter.getVideoUrl());
        trainChapterCreate.setDuration(chapter.getDuration());
        trainChapterCreate.setIsDisplay(chapter.getIsDisplay());
        trainChapterCreate.setSort(chapter.getSort());
        trainChapterCreate.setPlaybackNum(chapter.getPlaybackNum());
        trainChapterCreate.setArrange(chapter.getArrange());
        trainChapterCreate.setContent(chapter.getContent());
        return CommonResult.success(trainChapterCreate);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void displayChapter(Integer chapterId) {
        BizTrainChapter chapter = chapterMapper.selectById(chapterId);
        if (chapter == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        processChapterDisplay(chapter, chapter.getIsDisplay().equals(NEGATE) ? SURE : NEGATE);
        chapterMapper.updateById(chapter);

    }

    @Override
    public CommonResult getAllMembers(Integer trainId, TrainMembersQuery query) {
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_TRAINING) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        query.setNickName(query.getNickName() == null || query.getNickName().trim().isEmpty() ? null : query.getNickName().trim());
        query.setPhone(query.getPhone() == null || query.getPhone().trim().isEmpty() ? null : query.getPhone().trim());
        PageHelper.startPage(query.getPage(), query.getSize());
        List<TrainMembersDto> dtoList = trainMapper.getAllMembers(trainId, query.getNickName(), query.getPhone());
        Page<TrainMembers> trainMembers = copyPage(new Page<>(), dtoList);
        for (TrainMembersDto dto : dtoList) {
            trainMembers.add(TrainMembers.builder(dto));
        }
        return CommonResult.restPage(trainMembers);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteTrainMembers(Integer trainId, TrainMembersDelete membersDelete) {
        LocalDate now = LocalDate.now();
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || !content.getBizCategoryCode().equals(CODE_TRAINING) || content.getIsDisplay().equals(NEGATE)
                || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        BizTrainClass trainClass = classMapper.selectById(membersDelete.getClassId());
        if (trainClass == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        } else if (trainClass.getEndAt() != null && trainClass.getEndAt().isBefore(now)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        Long l = classMemberRelMapper.selectCount(new QueryWrapper<BizTrainClassMemberRel>().lambda()
                .eq(BizTrainClassMemberRel::getBizTrainClassId, membersDelete.getClassId())
                .eq(BizTrainClassMemberRel::getMemberId, membersDelete.getMemberId()));
        if (l == null || l != 1) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        classMemberRelMapper.delete(new QueryWrapper<BizTrainClassMemberRel>().lambda()
                .eq(BizTrainClassMemberRel::getBizTrainClassId, membersDelete.getClassId())
                .eq(BizTrainClassMemberRel::getMemberId, membersDelete.getMemberId()));
    }

    @Override
    public CommonResult getOptionalManage(Integer trainId, String name, String category) {
        String typeCode = null;
        if (!category.equals(CLASS_TEACHER)) {
            BizCoreContent content = coreContentMapper.selectById(trainId);
            if (content == null || content.getIsDeleted().equals(SURE)) {
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
            }
            typeCode = content.getTypeCode();
        }
        return CommonResult.success(identityMemberRelMapper.getOptionalManage(typeCode,
                name == null || name.trim().isEmpty() ? null : name, category));
    }

    @Override
    public CommonResult getOptionalTrainClasses(Integer trainId, String name) {
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || content.getIsDisplay().equals(NEGATE) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        List<CommonAll> result = new ArrayList<>();
        LambdaQueryWrapper<BizTrainClass> queryWrapper = new QueryWrapper<BizTrainClass>().lambda()
                .eq(BizTrainClass::getBizTrainId, trainId)
                .eq(BizTrainClass::getIsDisplay, SURE)
                .and(wrapper -> wrapper.isNull(BizTrainClass::getStartAt)
                        .or()
                        .gt(BizTrainClass::getStartAt, LocalDateTime.now()));
        if (name != null && !name.trim().isEmpty()) {
            queryWrapper.like(BizTrainClass::getName, name);
        }
        for (BizTrainClass trainClass : classMapper.selectList(queryWrapper)) {
            result.add(new CommonAll(trainClass.getId(), trainClass.getName()));
        }
        return CommonResult.success(result);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void assignToClass(TrainAssignMember assignMember, Integer trainId) {
        List<BizMessageSystem> messageSystems = new ArrayList<>();
        // 根据训练ID查询训练内容，确保训练内容存在且显示状态为正常。
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || content.getIsDisplay().equals(NEGATE) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }

        // 检查当前日期是否在训练班级开始日期之前，确保班级尚未开始。
        LocalDate now = LocalDate.now();
        BizTrainClass trainClass = classMapper.selectById(assignMember.getClassId());
        if (trainClass == null || trainClass.getIsDisplay().equals(NEGATE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        } else if (trainClass.getStartAt() != null && !now.isBefore(trainClass.getStartAt())) {
            throw new BaseException("训练营已开营");
        }
        for (Integer member : assignMember.getMembers()) {
            Long l = contentMemberRelMapper.selectCount(new QueryWrapper<BizCoreContentMemberRel>().lambda()
                    .eq(BizCoreContentMemberRel::getBizCoreContentId, trainClass.getBizTrainId())
                    .eq(BizCoreContentMemberRel::getMemberId, member));
            if (l == null || l == 0) {
                throw new BaseException("学员输入错误");
            }
        }

        Set<Integer> removeIds = new HashSet<>(6);

        // 遍历待分配的学员ID集合，校验每个学员是否符合分配条件。
        Set<Integer> memberIds = assignMember.getMembers();
        for (TrainAssignMemberDto dto : classMapper.getClassListByMemberList(memberIds.stream().toList(), trainId)) {
            // 检查学员是否已经在班级开营之后，如果是则不能分配。
            if (dto.getStartAt() != null && now.isAfter(dto.getStartAt())) {
                log.info("分配学员：班级已经开/结营，班级：{}, 学员：{}", dto.getClassName(), dto.getMemberId());
                throw new BaseException("学员所在班级已结营");
            } else if (!dto.getBizIdentityCode().equals(STUDENT)) {
                // 检查学员身份是否正确，如果不是学员则不能分配。
                log.info("分配学员：不是学员，班级：{}, 学员：{}, 身份：{}", dto.getClassName(), dto.getMemberId(), dto.getBizIdentityCode());
                throw new BaseException("人员不是学员");
            } else if (dto.getClassId().equals(trainClass.getId())) {
                continue;
            }
            // 更新学员和班级的关系信息。
            classMemberRelMapper.update(null, new UpdateWrapper<BizTrainClassMemberRel>().lambda()
                    .eq(BizTrainClassMemberRel::getId, dto.getId())
                    .set(BizTrainClassMemberRel::getBizTrainId, trainId)
                    .set(BizTrainClassMemberRel::getBizTrainClassId, trainClass.getId())
                    .set(BizTrainClassMemberRel::getMemberId, dto.getMemberId())
                    .set(BizTrainClassMemberRel::getBizIdentityId, dto.getBizIdentityId())
                    .set(BizTrainClassMemberRel::getBizIdentityCode, dto.getBizIdentityCode())
                    .set(BizTrainClassMemberRel::getIsVoteTop, NEGATE)
                    .set(BizTrainClassMemberRel::getCreateAt, LocalDateTime.now()));
            // 从待分配列表中移除已处理的学员ID。
            memberIds.remove(dto.getMemberId());
            removeIds.add(dto.getMemberId());
            BizMessageSystem messageSystem = messageSystemService.joinTheClass(trainClass.getName(), trainClass.getId(),
                    dto.getMemberId());
            messageSystems.add(messageSystem);
            taskMemberRelMapper.delete(new QueryWrapper<BizTrainTaskMemberRel>().lambda()
                    .eq(BizTrainTaskMemberRel::getBizTrainClassId, dto.getClassId())
                    .eq(BizTrainTaskMemberRel::getMemberId, dto.getMemberId()));
        }

        // 对于剩余未处理的学员ID，插入新的学员和班级关系记录。
        if (!memberIds.isEmpty()) {
            List<BizTrainClassMemberRel> relList = new ArrayList<>();
            // 查询学员身份信息，用于插入新的关系记录。
            BizIdentity identity = identityMapper.selectOne(new QueryWrapper<BizIdentity>().lambda().eq(BizIdentity::getCode, STUDENT));
            for (Integer memberId : memberIds) {
                BizTrainClassMemberRel rel = new BizTrainClassMemberRel();
                rel.setBizTrainId(trainId);
                rel.setBizTrainClassId(trainClass.getId());
                rel.setMemberId(memberId);
                rel.setBizIdentityId(identity.getId());
                rel.setBizIdentityCode(identity.getCode());
                rel.setCreateAt(LocalDateTime.now());
                relList.add(rel);
                BizMessageSystem messageSystem = messageSystemService.joinTheClass(trainClass.getName(),
                        trainClass.getId(), memberId);
                messageSystems.add(messageSystem);
            }
            // 批量插入新的关系记录。
            classMemberRelMapper.insertBatch(relList);
        }
        memberIds.addAll(removeIds);
        if (!memberIds.isEmpty()) {
            taskMemberRelMapper.initTaskMemberRelByMemberId(memberIds, trainClass.getId());
        }
        if (!messageSystems.isEmpty()) {
            messageSystemService.insertBatch(messageSystems);
        }
        EXECUTOR.execute(() -> updateNotice(memberIds, trainClass));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addOrUpdateHomework(Integer trainId, TrainHomeworkCreateOrUpdate params) {
        // 根据trainId查询培训核心内容，确认培训存在且可见
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || content.getIsDisplay().equals(NEGATE) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }

        // 查询现有的作业，根据条件和trainId
        BizTrainHomework homework = homeworkMapper.selectOne(new QueryWrapper<BizTrainHomework>().lambda()
                .eq(BizTrainHomework::getCondition, params.getCondition().trim())
                        .eq(BizTrainHomework::getTitle, params.getTitle().trim())
                        .eq(BizTrainHomework::getBizTrainId, trainId)
                .eq(BizTrainHomework::getIsDeleted, NEGATE));

        // 作业不存在且无ID时，新建作业
        if (params.getId() == null && homework == null) {
            homework = new BizTrainHomework();
            homework.setCondition(params.getCondition().trim());
            homework.setBizTrainId(trainId);
            homework.setCreateAt(LocalDateTime.now());
            homework.setTitle(params.getTitle().trim());
            homeworkMapper.insert(homework);
            homeworkClassMapper.initHomeworkClass(homework);
            // 有ID且作业不存在时，更新作业及其班级关联信息
        } else if (params.getId() != null && homework == null) {
            homeworkClassMapper.update(null, new UpdateWrapper<BizTrainHomeworkClass>().lambda()
                    .eq(BizTrainHomeworkClass::getBizTrainHomeworkId, params.getId())
                    .set(BizTrainHomeworkClass::getBizTrainId, trainId)
                    .set(BizTrainHomeworkClass::getCondition, params.getCondition().trim())
                    .set(BizTrainHomeworkClass::getTitle, params.getTitle().trim())
            );
            homeworkMapper.update(null, new UpdateWrapper<BizTrainHomework>().lambda()
                    .eq(BizTrainHomework::getId, params.getId())
                    .set(BizTrainHomework::getTitle, params.getTitle().trim())
                    .set(BizTrainHomework::getCondition, params.getCondition().trim()));
        // 有ID且作业已存在时，不做操作，记录日志
        } else if (params.getId() != null && params.getId().equals(homework.getId())) {
            log.info("创建/更新作业：不用操作");
        // 无ID且作业已存在，抛出异常
        } else {
            log.info("创建/更新作业：已有其他作业重负");
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
    }

    @Override
    public CommonResult getTrainHomework(Integer trainId, TrainHomeworkQuery query) {
        BizCoreContent coreContent = coreContentMapper.selectById(trainId);
        if (coreContent == null || coreContent.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        PageHelper.startPage(query.getPage(), query.getSize());
        LambdaQueryWrapper<BizTrainHomework> queryWrapper = new QueryWrapper<BizTrainHomework>().lambda()
                .eq(BizTrainHomework::getBizTrainId, trainId).eq(BizTrainHomework::getIsDeleted, NEGATE);
        if (query.getContent() != null) {
            queryWrapper.like(BizTrainHomework::getCondition, query.getContent());
        }
        List<BizTrainHomework> bizTrainHomeworks = homeworkMapper.selectList(queryWrapper);
        Page<TrainHomework> result = copyPage(new Page<>(), bizTrainHomeworks);
        for (BizTrainHomework bizTrainHomework : bizTrainHomeworks) {
            TrainHomework trainHomework = new TrainHomework();
            trainHomework.setId(bizTrainHomework.getId());
            trainHomework.setContent(bizTrainHomework.getCondition());
            trainHomework.setCreateAt(bizTrainHomework.getCreateAt());
            trainHomework.setTitle(bizTrainHomework.getTitle());
            result.add(trainHomework);
        }
        return CommonResult.restPage(result);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteHomework(Integer homeworkId, Integer trainId) {
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || content.getIsDisplay().equals(NEGATE) || content.getIsDeleted().equals(SURE)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        BizTrainHomework homework = homeworkMapper.selectById(homeworkId);
        if (homework == null || homework.getIsDeleted().equals(SURE) || !homework.getBizTrainId().equals(trainId)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        homework.setIsDeleted(SURE);
        homeworkMapper.updateById(homework);
        homeworkClassMapper.update(null, new UpdateWrapper<BizTrainHomeworkClass>().lambda()
                .eq(BizTrainHomeworkClass::getBizTrainHomeworkId, homeworkId)
                .set(BizTrainHomeworkClass::getPublishedAt, null)
                .set(BizTrainHomeworkClass::getIsEnabled, NEGATE)
                .set(BizTrainHomeworkClass::getIsDeleted, SURE));
    }

    @Override
    public CommonResult getTrainDown(String search) {
        LambdaQueryWrapper<BizCoreContent> queryWrapper = new QueryWrapper<BizCoreContent>().lambda()
                .eq(BizCoreContent::getBizCategoryCode, CODE_TRAINING)
                .eq(BizCoreContent::getIsDeleted, NEGATE)
                .eq(BizCoreContent::getIsDisplay, SURE)
                .orderByAsc(BizCoreContent::getSort).orderByAsc(BizCoreContent::getId);
        if (StringUtils.isNotBlank(search)) {
            queryWrapper.like(BizCoreContent::getTitle, search.trim());
        }
        List<CommonAll> result = new ArrayList<>();
        for (BizCoreContent content : coreContentMapper.selectList(queryWrapper)) {
            result.add(new CommonAll(content.getId(), content.getTitle()));
        }
        return CommonResult.success(result);
    }

    @Override
    public CommonResult getTrainType() {

        return CommonResult.success(trainTypeMapper.selectList(new QueryWrapper<>()));
    }

    /**
     * 校验班级管理角色的数量和有效性。
     *
     * @param typeCode 类型代码，用于校验身份成员关系。
     * @param assistantIds 助教ID集合。
     * @param mentorIds 导师ID集合。
     * @param trainerId 训练师ID。
     * @param classTeacherId 班主任ID。
     * 该方法主要校验以下几点：
     * 1. 助教、导师、训练师和班主任的ID集合总数量是否符合预期。
     * 2. 检查传入的助教ID集合对应的助教数量是否与期望一致。
     * 3. 检查传入的导师ID集合对应的导师数量是否与期望一致。
     * 4. 检查传入的训练师ID是否对应至少一个有效的训练师关系。
     * 5. 检查传入的班主任ID是否对应至少一个有效的班主任关系。
     * 若以上校验任一失败，将抛出参数错误异常。
     */
    private void checkClassManage(String typeCode, Set<Integer> assistantIds, Set<Integer> mentorIds, Integer trainerId,
                                  Integer classTeacherId) {
        // 将所有角色ID合并到一个集合中，并校验总数量是否符合预期
        int idNum = 0;
        Set<Integer> countIds = new HashSet<>(assistantIds);
        idNum += assistantIds.size();
        countIds.addAll(mentorIds);
        idNum += mentorIds.size();
        if (trainerId != null) {
            countIds.add(trainerId);
            idNum ++;
        }
        if (classTeacherId != null) {
            countIds.add(classTeacherId);
            idNum ++;
        }
        if (countIds.size() != idNum) {
            // +2是为了校验助教和导师的数量 + 教练 + 班主任的数量是否与countIds相等,判断教练、班主任是否有重复
            throw new BaseException("人员重复");
        }

        // 校验助教数量是否符合传入的ID数量
        if (!assistantIds.isEmpty()) {
            int assistantNum = identityMemberRelMapper.countByMemberAndIdentity(new ArrayList<>(assistantIds), CATEGORY_ASSISTANT, typeCode);
            if (assistantNum != assistantIds.size()) {
                throw new BaseException("助教人员错误");
            }
        }

        // 校验导师数量是否符合传入的ID数量
        if (!mentorIds.isEmpty()) {
            int mentorNum = identityMemberRelMapper.countByMemberAndIdentity(new ArrayList<>(mentorIds), CATEGORY_MENTOR, typeCode);
            if (mentorNum != mentorIds.size()) {
                throw new BaseException("导师人员错误");
            }
        }

        // 校验训练师数量是否至少为1
        if (trainerId != null) {
            int trainerNum = identityMemberRelMapper.countByMemberAndIdentity(List.of(trainerId), CATEGORY_TRAINER, typeCode);
            if (trainerNum != 1) {
                throw new BaseException("教练人员错误");
            }
        }

        // 校验班主任数量是否至少为1
        if (classTeacherId != null) {
            int classTeacherNum = identityMemberRelMapper.countByMemberAndIdentity(List.of(classTeacherId), CLASS_TEACHER, null);
            if (classTeacherNum != 1) {
                throw new BaseException("助教人员错误");
            }
        }
    }


    private void generateBizTrainClassMemberRel(Integer trainId, Integer classId, List<BizTrainClassMemberRel> relList,
                                                BizIdentity bizIdentity, Integer memberId) {
        if (memberId != null) {
            BizTrainClassMemberRel rel = new BizTrainClassMemberRel();
            rel.setBizTrainId(trainId);
            rel.setBizTrainClassId(classId);
            rel.setMemberId(memberId);
            rel.setBizIdentityId(bizIdentity.getId());
            rel.setBizIdentityCode(bizIdentity.getCode());
            rel.setCreateAt(LocalDateTime.now());
            relList.add(rel);
        }
    }

    private void processChapterDisplay(BizTrainChapter chapter, Integer targetStatus) {
        if (!chapter.getIsDisplay().equals(targetStatus)) {
            chapter.setIsDisplay(targetStatus);
            if (targetStatus.equals(NEGATE)) {
                chapterRelMapper.update(null, new UpdateWrapper<BizTrainClassChapterRel>().lambda()
                        .eq(BizTrainClassChapterRel::getBizTrainChapterId, chapter.getId())
                        .set(BizTrainClassChapterRel::getIsPublished, NEGATE));
            }
        }
    }

    private BizCoreContent generateTrain(CreateTrain createTrain, BizCategory category, BizCoreContent bizCoreContent) {
        LocalDateTime now = LocalDateTime.now();
        bizCoreContent.setBizCategoryId(category.getId());
        bizCoreContent.setBizCategoryCode(category.getCode());
        bizCoreContent.setTypeCode(createTrain.getTypeCode());
        bizCoreContent.setTitle(createTrain.getTitle());
        bizCoreContent.setDescription(createTrain.getDescription());
        bizCoreContent.setImageT(createTrain.getImageT());
        bizCoreContent.setImageV(createTrain.getImageV());
        bizCoreContent.setNum(createTrain.getNum());
        bizCoreContent.setCreateAt(now);
        bizCoreContent.setProfile(createTrain.getProfile());
        bizCoreContent.setUpdateAt(now);
        bizCoreContent.setIsDisplay(createTrain.getIsDisplay() == null ? NEGATE: createTrain.getIsDisplay());
        bizCoreContent.setIsCharge(createTrain.getIsCharge());
        if (createTrain.getIsCharge().equals(SURE)) {
            bizCoreContent.setOriginalPrice(createTrain.getOriginalPrice());
            bizCoreContent.setActualPrice(createTrain.getActualPrice());
        } else {
            bizCoreContent.setOriginalPrice(null);
            bizCoreContent.setActualPrice(null);
        }
        bizCoreContent.setDisplayAt(bizCoreContent.getIsDisplay().equals(NEGATE) ? null : now);
        return bizCoreContent;
    }

    private void checkType(String typeCode) {
        if (typeCode == null) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        switch (typeCode) {
            case TYPE_CODE_READING, TYPE_CODE_WRITING, TYPE_CODE_SPEECH, TYPE_CODE_VOICE:
                break;
            default:
                throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
    }

    private BizTrainChapter checkChapter(Integer chapterId, Integer trainId) {
        BizCoreContent content = coreContentMapper.selectById(trainId);
        if (content == null || content.getIsDeleted().equals(SURE) || !content.getBizCategoryCode().equals(CODE_TRAINING)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        BizTrainChapter chapter = chapterMapper.selectById(chapterId);
        if (chapter == null || chapter.getIsDeleted().equals(SURE) || !chapter.getBizTrainId().equals(trainId)) {
            throw new BaseException(ErrorCodeEnum.PARAMS_ERROR);
        }
        return chapter;
    }

    @Override
    public void test() {
//        Map<Integer, Set<BizTrainClassMemberRel>> tempMap = new LinkedHashMap<>();
//        for (BizTrainClassMemberRel rel : classMemberRelMapper.selectList(new QueryWrapper<>())) {
//            Set<BizTrainClassMemberRel> orDefault = tempMap.getOrDefault(rel.getBizTrainClassId(), new HashSet<>());
//            orDefault.add(rel);
//            tempMap.put(rel.getBizTrainClassId(), orDefault);
//        }
//        for (Map.Entry<Integer, Set<BizTrainClassMemberRel>> entry : tempMap.entrySet()) {
//            BizTrainClass trainClass = classMapper.selectById(entry.getKey());
//            if (trainClass == null) {
//                continue;
//            }
//            updateNotice1(entry.getValue(), trainClass);
//        }
//        Set<Integer> memberIds = new HashSet<>();
//        memberIds.add(3);
//        BizTrainClass bizTrainClass = classMapper.selectById(79);
//        updateNotice(memberIds, bizTrainClass);
    }

    public void updateNotice(Set<Integer> memberIds, BizTrainClass trainClass) {
        if (!memberIds.isEmpty()) {
            for (Member member : memberMapper.selectList(new QueryWrapper<Member>().lambda().in(Member::getId, memberIds))) {
                Resource resource = posterService.draw(PosterService.PosterParams.builder()
                        .type(PosterService.CLASS_NOTICE)
                        .nickName(member.getNickName())
                        .className(trainClass.getName())
                        .qrCodeScene(formatCodeScene(member.getCode(), null, null, null))
                        .date(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")))
                        .build());
                String s = aliService.putObject(String.format("%s_%s.png", trainClass.getId(), member.getCode()),
                        resource, "class_notice");
                if (s != null) {
                    classMemberRelMapper.update(null, new UpdateWrapper<BizTrainClassMemberRel>().lambda()
                            .eq(BizTrainClassMemberRel::getMemberId, member.getId())
                            .eq(BizTrainClassMemberRel::getBizTrainClassId, trainClass.getId())
                            .set(BizTrainClassMemberRel::getNoticeUrl, s));
                }
            }
        }
    }

    public void updateNotice1(Set<BizTrainClassMemberRel> memberIds, BizTrainClass trainClass) {
        if (!memberIds.isEmpty()) {
            for (BizTrainClassMemberRel rel : memberIds) {
                Member member = memberMapper.selectById(rel.getMemberId());
                Resource resource = posterService.draw(PosterService.PosterParams.builder()
                        .type(PosterService.CLASS_NOTICE)
                        .nickName(member.getNickName())
                        .className(trainClass.getName())
                        .qrCodeScene(formatCodeScene(member.getCode(), null, null, null))
                        .date(rel.getCreateAt().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")))
                        .build());
                String s = aliService.putObject(String.format("%s_%s.png", trainClass.getId(), member.getCode()),
                        resource, "class_notice");
                if (s != null) {
                    classMemberRelMapper.update(null, new UpdateWrapper<BizTrainClassMemberRel>().lambda()
                            .eq(BizTrainClassMemberRel::getMemberId, member.getId())
                            .eq(BizTrainClassMemberRel::getBizTrainClassId, trainClass.getId())
                            .set(BizTrainClassMemberRel::getNoticeUrl, s));
                }
            }
        }
    }
}
